{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python Basic\n",
    "PyRosetta顾名思义，是Rosetta的Python界面的API封装。因此本章节将以pyrosetta的一些例句为例，介绍一些关于python的**非常基础**语法和语句，以方便读者阅读和理解本系列教程的内容。\n",
    "\n",
    "更加详细的python教程课程可以再网络上找到很多，比如https://juejin.cn/post/6844903765410070535"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 0. 库与Import\n",
    "模块是一个包含所有你定义的函数和变量的文件，其后缀名是.py。模块可以被别的程序引入，以使用该模块中的函数等功能。在pyrosetta中所有的函数和方法都是定义在rosetta.io文件中(C++)的。但和一般的python标准库的导入方法类似。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入pyrosetta\n",
    "import pyrosetta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 也可以等价写于:\n",
    "from pyrosetta import init"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "导入了函数或某个函数的上级的库，我们就可以来调用这个函数来实现一些功能了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PyRosetta-4 2020 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release 2020.23+release.0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 2020-06-04T19:12:24] retrieved from: http://www.pyrosetta.org\n",
      "(C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team.\n",
      "\u001b[0mcore.init: {0} \u001b[0mChecking for fconfig files in pwd and ./rosetta/flags\n",
      "\u001b[0mcore.init: {0} \u001b[0mRosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release r257 2020.23+release.0d6f90a8cb9 0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 http://www.pyrosetta.org 2020-06-04T19:12:24\n",
      "\u001b[0mcore.init: {0} \u001b[0mcommand: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0m'RNG device' seed mode, using '/dev/urandom', seed=-573114774 seed_offset=0 real_seed=-573114774 thread_index=0\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0mRandomGenerator:init: Normal mode, seed=-573114774 RG_type=mt19937\n"
     ]
    }
   ],
   "source": [
    "# 使用这个函数的方法1:库名+\".\"+函数。“.”代表在指定在这个库中寻找我们需要的函数。\n",
    "pyrosetta.init()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PyRosetta-4 2020 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release 2020.23+release.0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 2020-06-04T19:12:24] retrieved from: http://www.pyrosetta.org\n",
      "(C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team.\n",
      "\u001b[0mcore.init: {0} \u001b[0mChecking for fconfig files in pwd and ./rosetta/flags\n",
      "\u001b[0mcore.init: {0} \u001b[0mRosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release r257 2020.23+release.0d6f90a8cb9 0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 http://www.pyrosetta.org 2020-06-04T19:12:24\n",
      "\u001b[0mcore.init: {0} \u001b[0mcommand: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0m'RNG device' seed mode, using '/dev/urandom', seed=-578603057 seed_offset=0 real_seed=-578603057 thread_index=0\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0mRandomGenerator:init: Normal mode, seed=-578603057 RG_type=mt19937\n"
     ]
    }
   ],
   "source": [
    "# 也可以这样来调用, 因为 我们先前已经指定了 from pyrosetta import init。从pyrosetta中导入叫init的函数。\n",
    "init()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 提示:\n",
    "如此一来，pyrosetta在我们的内存中就已经激活了。\n",
    "\n",
    "在运行pyrosetta的任何函数之前，**一定记得进行初始化。** 否则将会报错。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 变量与数据类型\n",
    "PyRosetta和Python能处理的数据类型类似:\n",
    "- 整数\n",
    "- 浮点数\n",
    "- 字符串\n",
    "- 布尔值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 列表与切片\n",
    "在Python中列表和切片是非常重要的概念，此处我们以一些简单的例子来说明;\n",
    "\n",
    "**列表** 就是用“[]”符号，将一系列的变量和数据以“,”分隔的一个数据格式。\n",
    "\n",
    "**切片** 就是用索引号去获取列表中的某个或某个范围内的数据，并返回值或列表。但是注意索引的顺序是从0开始。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建一个列表: \n",
    "mylist = [1, 2, 3, 4, 5, 6]\n",
    "\n",
    "# 索引: 第一个元素:\n",
    "mylist[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 索引: 一个范围, 第二个元素到第三个元素:\n",
    "mylist[1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因此所有pyrosetta返回的数据类型，只要是列表，就可以使用索引切片进行数据获取。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. For循环\n",
    "循环在数据分析中具有重要的作用。\n",
    "\n",
    "使用for…in 循环是python最简单理解的一种循环方式，可以直白的逻辑可以理解为:\n",
    "```\n",
    "for(对于)。。in(在某个集合)中的元素进行循环。\n",
    "```\n",
    "举例，我想对一个列表循环并将这个列表中的所有值进行打印:\n",
    "\n",
    "print()函数代表，将“()”中的内容进行打印输出到屏幕上。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "# 循环:\n",
    "for x in mylist:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "for x in mylist: 代表在mylist中的元素x进行循环。而且对于每个循环需要做的处理就是print()。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Def(函数)\n",
    "函数是组织好的，可重复使用的，用来实现单一，或相关联功能的代码段。\n",
    "函数能提高应用的模块性，和代码的重复利用率。你已经知道Python提供了许多内建函数，比如print()。但你也可以自己创建函数，这被叫做用户自定义函数。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义一个函数:\n",
    "def init_pyrosetta():\n",
    "    import pyrosetta\n",
    "    pyrosetta.init()\n",
    "    return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PyRosetta-4 2020 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release 2020.23+release.0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 2020-06-04T19:12:24] retrieved from: http://www.pyrosetta.org\n",
      "(C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team.\n",
      "\u001b[0mcore.init: {0} \u001b[0mChecking for fconfig files in pwd and ./rosetta/flags\n",
      "\u001b[0mcore.init: {0} \u001b[0mRosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release r257 2020.23+release.0d6f90a8cb9 0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 http://www.pyrosetta.org 2020-06-04T19:12:24\n",
      "\u001b[0mcore.init: {0} \u001b[0mcommand: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0m'RNG device' seed mode, using '/dev/urandom', seed=1475936894 seed_offset=0 real_seed=1475936894 thread_index=0\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0mRandomGenerator:init: Normal mode, seed=1475936894 RG_type=mt19937\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 调用函数::\n",
    "init_pyrosetta()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Class(类)\n",
    "（新手向: 也可以简单地理解为一些函数的集合!）\n",
    "\n",
    "在Python中，定义类是通过class关键字, class后面紧接着是类名(用户自定义)，类名通常是大写开头的单词，紧接着是object(指明类从哪继承)。\n",
    "\n",
    "类中最重要的两个概念是:\n",
    "- 方法\n",
    "- 属性\n",
    "\n",
    "\n",
    "**1. 类中的函数即称为方法**。\n",
    "\n",
    "`__init__()` 是函数的构造方法，每档创建新实例时 Python 都会自动运行它。注意构造方法名字必须是这个，是规定好的。\n",
    "\n",
    "print_words函数 是类test的一个方法。\n",
    "\n",
    "**2. 类中的变量即称为属性**。\n",
    "\n",
    "self.words 是类的一个属性，__init__()函在实例化的过程中，将外部输入的words转换为内部的一个属性。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 一个类的代码示例:\n",
    "class test(object):\n",
    "\n",
    "    def __init__(self, words):\n",
    "        self.words = words\n",
    "\n",
    "    def print_words(self):\n",
    "        print(self.words)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可见，类是抽象的模板，是属性和方法抽象的模板，但类进行实例化(传递参数时)，类创建出来的一个个具体的“对象”。\n",
    "\n",
    "有了对象之后，然后方可调用其中的方法(函数);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "# 实例化，通过传递参数’hello‘。并实例化test。\n",
    "test1 = test('hello')\n",
    "\n",
    "# 使用类中的方法: 实例化的变量名+'.'+函数名(传递的参数，如果有的话)。\n",
    "test1.print_words()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行类中的方法实现了打印我们最开始传递的参数“hello”。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. PyRosetta Class & Function的使用**\n",
    "在PyRosetta中, 所有的功能相关的代码都是封装在类和函数当中的，因此我们只需要学会如何调用这些功能，就能达到学习和应用的目的。\n",
    "区分函数和类的使用也十分简单。可直接在PyRosetta的API网站中查询，一般而言，如果是类，那么都是以class字段直接开头。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果是函数: 就可以直接调用。比如我们想从序列直接生成结构，可以使用**pose_from_sequence函数**。\n",
    "![Alt Text](./img/pyrosetta_function.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[0mcore.chemical.GlobalResidueTypeSet: {0} \u001b[0mFinished initializing fa_standard residue type set.  Created 980 residue types\n",
      "\u001b[0mcore.chemical.GlobalResidueTypeSet: {0} \u001b[0mTotal time to initialize 0.734775 seconds.\n"
     ]
    }
   ],
   "source": [
    "# 调用函数的例子:\n",
    "from pyrosetta.io import pose_from_sequence\n",
    "pose = pose_from_sequence('AAAAAAA')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果是一个类，那么我们必须首先对他进行实例化，才能使用它。\n",
    "比如:\n",
    "![Alt Text](./img/pyrosetta_class.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入类\n",
    "from pyrosetta.rosetta.protocols.minimization_packing import MinMover\n",
    "\n",
    "# 实例化，并赋予一个变量名。\n",
    "minmover = MinMover()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PyRosetta的类被实例化后，大多数负责执行功能的都是叫apply()的函数，该函数接受的对象也大多数是Rosetta的Pose对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运行类，执行结构进行能量最小化。\n",
    "minmover.apply(pose)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**有的时候一些类会强制用户传递必要的参数才能实例化**\n",
    "\n",
    "还是以MinMover作为例子，在实例化过程中，如果没有传递参数。那么类会有一些默认的设置。\n",
    "\n",
    "当然用户也可以传递自己想要的参数进去，但是必须满足参数的格式要求，如init3, 用户需要传递4个参数，才能实例化这个类。\n",
    "\n",
    "![Alt Text](./img/class_init_doc.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进阶阅读"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. What is a \"Size\" or a \"Real\"?\n",
    "\n",
    "Within Rosetta, several simple objects are used for basic data structures. If these are seen within PyRosetta help, they can be replaced by their appropriate Python data type.\n",
    "    Size in an int\n",
    "    Real is a double or float (use float in Python)\n",
    "    Vector or Vector1 often serves the purpose of a Python list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. Where are Vector objects?\n",
    "\n",
    "Within Rosetta, Vector objects are used for various list structures. The common Vector objects are found in various locations. Please consult the question below for more information.\n",
    " Vector1                     \n",
    " rosetta.Vector1                       \n",
    " xyzVector\n",
    " rosetta.numeric.xyzVector          \n",
    " vector1_(data type)\n",
    " rosetta.utility.vector1_(data type)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. Why are Rosetta objects 1-indexed?\n",
    "\n",
    "Within Rosetta has its roots in FORTRAN so counting is \"1-indexed\" (the first element is numbered 1). Python on the other hand is \"0-indexed\" (the first element is numbered 0). The documentation discusses this in a little more depth."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4.  How do I construct Rosetta Vector0/Vector1 objects?\n",
    "\n",
    "Vector0/1 is exposed in newer versions of PyRosetta and lives in pyrosetta.rosetta.utility.vector{0/1}_*. Specific Vector1 objects live in rosetta.utility.vector1_type.\n",
    "\n",
    "There is also pyrosetta.Vector1 helper function that will do construction of most common types using Python list as input. For or example:\n",
    "    print rosetta.Vector1( [ 1 , 2 , 3 ] )\n",
    "    print rosetta.Vector1( [ 1.0 , 2.0 , 3.0 ] )\n",
    "    print rosetta.Vector1( [ True , False , True ] )\n",
    "    print rosetta.Vector1( [ 'a' , 'b' , 'c' ] )\n",
    "\n",
    "    v = rosetta.utility.vector1_SSize()\n",
    "    v.append( 1 )\n",
    "    print v\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 5.  How do I construct various C++ std objects, like std::map?\n",
    "\n",
    "C++ sts:: types is exposed in PyRosetta in pyrosetta.rosetta.std module. For example all map types could be accessed as: pyrosetta.rosetta.std.map_type1_type2.\n",
    "\n",
    "For example:\n",
    "    m = pyrosetta.rosetta.std.map_string_Real()\n",
    "    m['aaa'] = 1.0;  m['bb']= 3.0\n",
    "    print m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 6.  How do I construct std::set objects?\n",
    "\n",
    "std::set templates is exposed in PyRosetta and lives in pyrosetta.rosetta.std_*. There is also helper function Set that will convert Python list/set object into  PyRosetta, it could be found in pyrosetta namespace:\n",
    "\n",
    "    print pyrosetta.Set( [ 1 , 2 , 3 ] )\n",
    "    print pyrosetta.Set( [ 1.0 , 2.0 , 3.0 ] )\n",
    "    print pyrosetta.Set( [ 'a' , 'b' , 'c' ] )\n",
    "\n",
    "    s = pyrosetta.utility.Set_SSize()\n",
    "    s.add(1);  s.add(2);  s.add(1);  s.erase(2)\n",
    "    print s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 7.  How do I convert \"AP\" or \"CAP\" objects to regular class objects?\n",
    "\n",
    "Use the \"get\" function (rosetta.utility.utility___getCAP in older releases). This is an involved issue which does not come up in common usage of PyRosetta.\n",
    "For example, to create a \"ALA\" residue:\n",
    "(new way)\n",
    "    chm = rosetta.core.chemical.ChemicalManager.get_instance()\n",
    "    rts = chm.residue_type_set( 'fa_standard' ).get()\n",
    "    ala = rosetta.core.conformation.ResidueFactory.create_residue( rts.name_map( 'ALA' ) )\n",
    "    print ala\n",
    "\n",
    "(old way)\n",
    "    chm = rosetta.core.chemical.ChemicalManager.get_instance()\n",
    "    rts_AP = chm.residue_type_set( 'fa_standard' )\n",
    "    rts = rosetta.utility.utility___getCAP( rts_AP )    # converts a CAP object to a ResidueTypeSet object\n",
    "    ala = rosetta.core.conformation.ResidueFactory.create_residue( rts.name_map( 'ALA' ) )\n",
    "    print ala"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 8.  How do I use std::ostream or std::istream for methods that require it?  \n",
    "\n",
    "The objects std::ostream and std::istream are bound in PyRosetta as  pyrosetta.rosetta.std.ostream and pyrosetta.rosetta.std.istream, respectively. Generally, objects that require these objects will also accept classes that are pyrosetta.rosetta.std.istringstream  and pyrosetta.rosetta.std.ostringstream objects.  Use these types of objects instead."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyrosetta",
   "language": "python",
   "name": "pyrosetta"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
